﻿using System;
using System.Linq;
using Castle.MonoRail.Framework;
using Castle.MonoRail.Framework.Filters;
using StateTheaterDataModel;
using System.Security.Principal;

namespace StateTheater.Controllers
{
	[Layout("default"), Rescue("generalerror")]
	[Filter(ExecuteWhen.BeforeAction, typeof(MobileFilter))]
	public class DirectoryController : SmartDispatcherController
	{
		StateTheaterDataContext db;
		public DirectoryController(StateTheaterDataContext db)
		{
			this.db = db;
		}

		public void List()
		{
			List('A');
		}

		public void List(char letter)
		{
			Func<Category, bool> whereC;
			if (letter == '0')
				whereC = (Category c) => Char.IsDigit(c.CategoryName[0]);
			else
				whereC = (Category c) => c.CategoryName[0] == letter;

			var cat = from c in db.Categories.Where(whereC)
					  select new
					  {
						  Id = c.CategoryID,
						  Name = c.CategoryName
					  };

			PropertyBag["list"] = cat.ToList();
			PropertyBag["letter"] = letter.ToString();
		}

		public void List(int id)
		{
			// If true, set to false.
			// if already false, don't change it, because this mean it a recycled datacontext 
			// which we've already changed, and you can it again after it's been read.
			if (db.ObjectTrackingEnabled)
				db.ObjectTrackingEnabled = false;

			var suppliers = (from ss in db.SuppliersInCategories 
							where ss.CategoryID == id && ss.Supplier.active
							orderby ss.Supplier.SupplierName
							select ss.Supplier).ToList();

			
			string user = this.Context.CurrentUser.Identity.Name;
			bool isAdmin = this.Context.CurrentUser.IsInRole("Admin") ;

			foreach (Supplier s in suppliers)
			{
				s.City = s.City == null ? "" : s.City.Trim();
				if (String.IsNullOrEmpty(s.Address))
					s.Address = "";
				else
					s.Address = s.Address.Trim().Replace("\n", "<br/>");

				if (s.WWWPage != null &&  s.WWWPage.Length > 2)
				{
					if (!s.WWWPage.StartsWith("http"))
					{
						s.WWWPage = "http://" + s.WWWPage;
					}
				}
				else
					s.WWWPage = null;

				// I'm hijacking s.active since it's easier than creating an new type.
				s.active = (isAdmin || (s.ModUser ?? "").Equals(user, StringComparison.CurrentCultureIgnoreCase));

				if (!string.IsNullOrEmpty(s.EmailAddress))
					s.EmailAddress = Util.Encode(s.EmailAddress);
			}

			PropertyBag["Suppliers"] = suppliers;

			char c = (from C in db.Categories
					  where C.CategoryID == id
					  select C.CategoryName[0]).First();
			List(c);
//				db.Dispose();			
		}

		public void vCard(int id)
		{
			var q = (
				from s in db.Suppliers
				where s.SupplierID == id
				select new
				{
					Name = s.SupplierName,
					s.PhoneNumber,
					s.FaxNumber,
					Address = s.Address,
					s.City,
					s.State,
					s.PostalCode,
					s.EmailAddress,
					s.WWWPage,
					s.Notes
				}).First();

			PropertyBag["Name"] = q.Name.Trim();
			PropertyBag["Address"] = (q.Address ??"").Trim().Replace('\n', ' ');
			PropertyBag["City"] = (q.City ??"").Trim();
			PropertyBag["State"] = (q.State ??"").Trim();
			PropertyBag["PostalCode"] = (q.PostalCode ??"").Trim();
			PropertyBag["PhoneNumber"] = Util.FixPhone(q.PhoneNumber ??"");
			PropertyBag["FaxNumber"] = Util.FixPhone(q.FaxNumber ??"");
			PropertyBag["WWWPage"] = q.WWWPage ??"";
			PropertyBag["EmailAddress"] = q.EmailAddress ??"";
			PropertyBag["Notes"] = q.Notes;
			PropertyBag["Today"] = DateTime.Now.ToUniversalTime().ToString("yyyyMMddTHHmmssZ");
			Response.ContentType = "text/x-vcard";
			CancelLayout();


		}

		public void Add()
		{
			Edit(new Supplier());
			this.SelectedViewName = @"Directory\Edit";
		}

		public void Edit([DataBind("supplier")] Supplier supplier)
		{
			PropertyBag["supplier"] = supplier;
			var categories = db.SuppliersInCategories.Where(sc=>sc.SupplierID == supplier.SupplierID).Select(c=>c.Category).ToList();
			PropertyBag["selectedCategories"] = categories ;
			PropertyBag["allCategories"] = db.Categories.OrderBy(c=>c.CategoryName.ToUpper()).ToList();
			if (categories != null && categories.Count > 0)
				PropertyBag["topcategory"] = categories[0].CategoryID;
			else
				PropertyBag["topcategory"] = "";

		}

		public void Edit(int ID)
		{
			Edit(db.Suppliers.First(s => s.SupplierID == ID));
		}

		public void Save([DataBind("supplier")] Supplier supplier)
		{
			PropertyBag["supplier"] = supplier;

			supplier.ModUser = this.Context.CurrentUser.Identity.Name;
			supplier.ModTime = DateTime.Now;

			Supplier old = db.Suppliers.FirstOrDefault(s => s.SupplierID == supplier.SupplierID);
			if (old != null)
			{
				old.active = supplier.active;
				old.Address = supplier.Address;
				old.City = supplier.City;
				old.EmailAddress = supplier.EmailAddress;
				old.FaxNumber = supplier.FaxNumber;
				old.ModTime = supplier.ModTime;
				old.ModUser = supplier.ModUser;
				old.Notes = supplier.Notes;
				old.PhoneNumber = supplier.PhoneNumber;
				old.PostalCode = supplier.PostalCode;
				old.State = old.State;
				old.SupplierName = supplier.SupplierName;
				old.WWWPage = supplier.WWWPage;
				db.SuppliersInCategories.DeleteAllOnSubmit(db.SuppliersInCategories.Where(sc=>sc.SupplierID == supplier.SupplierID) );
				int numCats = db.Categories.Count();
				const string paramFormat = "selectedCategories[{0}].CategoryID";
				for (int i = 0; i < numCats; ++i)
				{
					string param = String.Format(paramFormat, i);
					int catid;
					if (Int32.TryParse(this.Params[param], out catid))
					{
						SuppliersInCategory sc = new SuppliersInCategory();
						sc.SupplierID = supplier.SupplierID;
						sc.CategoryID = catid;
						sc.ModTime = DateTime.Now;
						sc.ModUser = this.Context.CurrentUser.Identity.Name;
						db.SuppliersInCategories.InsertOnSubmit(sc);
					}
				}
				string newcat1 = Params["NewCat-1"] as string;
				if (!String.IsNullOrEmpty(newcat1))
				{
					AddSupplierInNewCategory(supplier.SupplierID, newcat1);
				}
				string newcat2 = Params["NewCat-2"] as string;
				if (!String.IsNullOrEmpty(newcat2))
				{
					AddSupplierInNewCategory(supplier.SupplierID, newcat2);
				}
			}
			else
				db.Suppliers.InsertOnSubmit(supplier);

			db.SubmitChanges();

			PropertyBag.Add("Supp", db.Suppliers.Where(su => su.SupplierID == supplier.SupplierID).First());
			PropertyBag.Add("Cats", db.SuppliersInCategories.Where(su => su.SupplierID == supplier.SupplierID).Select(sc => sc.Category.CategoryName).ToArray());
			AdminController.RecordUserAction(db, this, "supplier", supplier.SupplierID, this.PropertyBag);

			Edit(supplier.SupplierID);
		}

		private void AddSupplierInNewCategory(int supplierID, string newcat)
		{
			Category cat = db.Categories.Where(c => c.CategoryName == newcat).FirstOrDefault();
			if (cat == null)
			{
				cat = new Category(newcat, this.Context.CurrentUser.Identity.Name);
				int cnt = db.FORUM_MEMBERs.Where(m => m.M_NAME == cat.ModUser).Count();
				System.Diagnostics.Trace.Assert(cnt == 1, "User not found");
				db.Categories.InsertOnSubmit(cat);
			}
			SuppliersInCategory sc1 = new SuppliersInCategory();
			sc1.SupplierID = supplierID;
			sc1.ModTime = DateTime.Now;
			sc1.ModUser = this.Context.CurrentUser.Identity.Name;
			cat.SuppliersInCategories.Add(sc1);
		}

		public void Delete(int ID)
		{
			if (this.Context.CurrentUser.IsInRole("Admin"))
			{
				var supp = db.Suppliers.FirstOrDefault(su => su.SupplierID == ID);
				if (supp != null)
				{
					db.Suppliers.DeleteOnSubmit(supp);
					db.SubmitChanges();
					PropertyBag["Text"] = supp.SupplierName + " Deleted";
				}
				else
				{
					PropertyBag["Text"] = "Supplier not found";
				}
			}
			else
			{
				PropertyBag["Text"] = "You must be logged in and authorized.";
			}
			this.SelectedViewName = "status";
		}

		public void Approve(int ID)
		{
			if (this.Context.CurrentUser.IsInRole("Admin"))
			{
				var supp = db.Suppliers.FirstOrDefault(su => su.SupplierID == ID);
				if (supp != null)
				{
					supp.active = true;
					db.SubmitChanges();
					PropertyBag["Text"] = supp.SupplierName + " Activated";
				}
				else
				{
					PropertyBag["Text"] = "Supplier not found";
				}
			}
			else
			{
				PropertyBag["Text"] = "You must be logged in and authorized.";
			}
			this.SelectedViewName = "status";

		}

	}

}
